package 泛型;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;

//import java.lang.reflect.Array;


/*class Queue<E> {
	private E[] elements;
	private int head = 0, tail = 0;

	Queue(int size) {
		elements = (E[]) new Object[size];
	}

	void insert(E element) throws QueueFullException {
		if (isFull())
			throw new QueueFullException();
		elements[tail] = element;
		tail = (tail + 1) % elements.length;
	}

	E remove() throws QueueEmptyException {
		if (isEmpty()) {
			throw new QueueEmptyException();
		}
		E element = elements[head];
		head = (head + 1) % elements.length;
		return element;
	}

	boolean isEmpty() {
		return head == tail;
	}

	boolean isFull() {
		return (tail + 1) % elements.length == head;
	}
}

class QueueEmptyException extends Exception {
}

class QueueFullException extends Exception {
}

public class Test1 {
	public static void main(String[] args) throws QueueFullException, QueueEmptyException {
		Queue<String> queue = new Queue<String>(6);
		System.out.println("Empty: " + queue.isEmpty());
		System.out.println("Full: " + queue.isFull());
		queue.insert("A");
		queue.insert("B");
		queue.insert("C");
		queue.insert("D");
		queue.insert("E");
		System.out.println("Empty: " + queue.isEmpty());
		System.out.println("Full: " + queue.isFull());
		System.out.println("Removing " + queue.remove());
		System.out.println("Empty: " + queue.isEmpty());
		System.out.println("Full: " + queue.isFull());
		System.out.println("Adding F");
		queue.insert("F");
		while (!queue.isEmpty()) {
			System.out.println("Removing " + queue.remove());
		}

		System.out.println("Empty: " + queue.isEmpty());
		System.out.println("Full: " + queue.isFull());
	}
}*/
/*
//通配符的使用：擦除带来的问题
class HasF {
	public void f() {
		System.out.println("HasF.f()");
	}
}

class otherClass extends HasF {
	public void f() {
		System.out.println("otherClass.f()");
	}
}

class Manipulator3 {// 不设置泛型，也能解决此类问题。
	private HasF obj;

	public Manipulator3(HasF x) {
		obj = x;
	}

	public void manipulate() {
		obj.f();
	}
}

//public class Test1<T> {//出错，因为泛型擦除
public class Test1<T extends HasF> {// 设置一个上界，凡是T处皆用实际代入的类替代（如：HasF，otherClass），只要代入的类为HasF及子类都可
	private T obj;

	public Test1(T obj) {
		this.obj = obj;
	}

	public void manipulate() {
		System.out.println(obj.getClass().getSimpleName());// 显示HasF及otherClass，说明T分别用HasF和otherClass替代
		obj.f(); // 当未设置上界时，无法编译 找不到符号 f()
	}

	public static void main(String[] args) {
		HasF hasF = new HasF();
		Test1<HasF> manipulator = new Test1<>(hasF);// HasF类代入
		manipulator.manipulate();// HasF.f()
		otherClass otherhasf = new otherClass();
		Test1<otherClass> manipulator1 = new Test1<>(otherhasf);// HasF类的子类otherClass代入
		manipulator1.manipulate();// otherClass.f()

		// 利用Manipulator3类方式，也能实现同样功能。所以泛型只有在比较复杂的类中才体现出作用。
		Manipulator3 manipulator30 = new Manipulator3(hasF);
		Manipulator3 manipulator31 = new Manipulator3(otherhasf);
		manipulator30.manipulate();// HasF.f()
		manipulator31.manipulate();// otherClass.f()

	}
}
*/
/*
//传递一个工厂对象并且通过它创建新的实例
interface FactoryI<T> {
	T create();
}
class Foo2<T> {
	private T x;
	public <F extends FactoryI<T>> Foo2(F factory) {//传递 factory对象，类似implement Factory,但可暂不实现接口方法
		x = factory.create();
	}
	// ...
}
class IntegerFactory implements FactoryI<Integer> {
	public Integer create() {// Integer -->T 并实现接口FactoryI方法
		return Integer.valueOf(0);
	}
}
class Widget {
	public static class Factory implements FactoryI<Widget> {
		public Widget create() {
			return new Widget();
		}
	}
}
//public class FactoryConstraint {
public class Test1 {
	public static void main(String[] args) {
		Foo2<Integer> integerFoo2=new Foo2<Integer>(new IntegerFactory());
		Foo2 <Widget> widgetFoo2=new Foo2<Widget>(new Widget.Factory());
		System.out.println(new Foo2<Integer>(new IntegerFactory()));
		System.out.println();
		IntegerFactory iFactory=new IntegerFactory();
		System.out.print(iFactory.getClass().getSimpleName());
		Factory widget=new Widget.Factory();
	}
}
*/
/*
//生成XX类实例：即生成泛型类实例
abstract class GenericWithCreate<T> {
	final T element;

	GenericWithCreate() {
		element = create();
	}

	abstract T create();
}

class XX {
}

class Creator extends GenericWithCreate<XX> {
	XX create() {//实现抽象类GenericWithCreate的方法create()
		return new XX();
	}
//class Creator extends GenericWithCreate<Integer> {
//	Integer create() {//实现抽象类GenericWithCreate的方法create()
//		return Integer.valueOf(0);
//}
//class Creator extends GenericWithCreate<String> {
//	String create() {//实现抽象类GenericWithCreate的方法create()
//		return new String();
//	}

	void f() {
		System.out.println(element.getClass().getSimpleName());// XX
	}
}

public class Test1 {
	public static void main(String[] args) throws Exception {
		Creator c = new Creator();
		c.f();
		
		Class<String> clazz0 = String.class;
		//String str = clazz.newInstance();//弃用，由clazz.getDeclaredConstructor().newInstance()代替
		String str=clazz0.getDeclaredConstructor().newInstance();
		
		Class<Integer> clazz = Integer.class;
		Constructor<Integer> cons = clazz.getDeclaredConstructor(int.class);
		Integer i = cons.newInstance(123);
		
	}
}
*/
/*
abstract class gc<T>{
	final T element;//欲生成的类实例
	gc(){
		element=creator();
	}
	abstract T creator();
}
class XX{}//欲生成的类
class Creator extends gc<XX>{
	XX creator() {//实现父类方法
		System.out.println(element);//null
		return new XX();
	}
	void f() {
		System.out.println(element.getClass().getSimpleName());
	}
}
public class Test1{
	public static void main(String[] args) {
		Creator c=new Creator();
		System.out.println(c.element.getClass());//class 泛型.XX
		c.f();
	}
}
*/
/*
public class Test1 {//如何创建泛型数组
   static final int SIZE = 100;
   static Generic<Integer>[] gia;
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
       // Compiles; produces ClassCastException:
       //! gia = (Generic<Integer>[])new Object[SIZE];
       // Runtime type is the raw (erased) type:
       gia = (Generic<Integer>[])new Generic[SIZE];
       System.out.println(gia.getClass().getSimpleName());
       gia[0] = new Generic<Integer>(0);
       //! gia[1] = new Object(); // Compile-time error
       // Discovers type mismatch at compile time:
       //! gia[2] = new Generic<Double>();
       Generic<Integer> g = gia[0];
   }
} *///*输出：Generic[]
/*
//创建泛型数组(数组为泛型，数组项为确定类，即：不同的类组成的数组，如：可以是：String、Integer或Person等数组项,数组项是确定的类，不带泛型)
public class Test1<T> {
   private Object[] array;
   public Test1(int sz) {
       array = new Object[sz];
   }
   public void put(int index, T item) {
       array[index] = item;
   }
   @SuppressWarnings("unchecked")
   public T get(int index) {
   	System.out.print("--");
   	return (T)array[index]; 
   }
   @SuppressWarnings("unchecked")
   public T[] rep() {
       return (T[])array; // Warning: unchecked cast
   }
   public static void main(String[] args) {
       Test1<String> gai =new Test1<String>(10);
       for(int i = 0; i < 10; i ++) {gai.put(i, String.valueOf(i));}
       for(int i = 0; i < 10; i ++) {System.out.print(gai.get(i) + " ");}
       System.out.println("-------");
       try {
           String[] ia = gai.rep();
           System.out.println("ddd");
       } catch(Exception e) { System.out.println(e); }
   }
} 
*/

//其实使用 Class 对象作为类型标识,创建泛型数组,是更好的设计：
/*
public class Test1<T> {
    private T[] array;//拟定义的数组，数组成员为泛型类，可以是：Integer、String、Person
    @SuppressWarnings("unchecked")
    public Test1(Class<T> type, int sz) {
       array = (T[])Array.newInstance(type, sz);//调用Array静态方法，生成数组实例
    }
    public void put(int index, T item) {
        array[index] = item;
    }
    public T get(int index) {
   	 return array[index]; 
    }
    public T[] rep() { 
   	 return array; 
    }
    public static void main(String[] args) {
        Test1<Integer> gai =new Test1<Integer>(Integer.class, 10);//创建整型数组
        for(int i = 0; i < 10; i ++) {gai.put(i, i);}
        for(int i = 0; i < 10; i ++) {System.out.print(gai.get(i) + " ");}
        System.out.println();
        Integer[] ia = gai.rep();
        for(int i = 0; i < 10; i ++) {System.out.print(ia[i] + " ");}
        System.out.println();
        
        Test1<String> ga =new Test1<String>(String.class, 10);//创建String型数组
        for(int i = 0; i < 10; i ++) {ga.put(i, String.valueOf(i));}
        for(int i = 0; i < 10; i ++) {System.out.print(gai.get(i) + " ");}
        System.out.println();
        String[] ias = ga.rep();
        for(int i = 0; i < 10; i ++) {System.out.print(ias[i] + " ");}
        System.out.println();
        
        Test1<Person> persons=new Test1<Person>(Person.class, 4);//创建Person型数组
        persons.put(0, new Person(1, "张三"));
        persons.put(1, new Person(2, "李四"));
        persons.put(2, new Person(3, "王五"));
        for (int i=0;i<3;i++) System.out.println(persons.get(i));
        System.out.println();
        Person[] iap = persons.rep();
        for(int i = 0; i < 3; i ++) {System.out.print(iap[i] + " ");}
        System.out.println();
        
    }
}
class Person{
	Integer id;
	String name;

	public Person(Integer id, String name) {
		super();
		this.id = id;
		this.name = name;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	public String toString() {
		return "[ id="+id+" name="+name+" ]";
	}
}
*/
// 创建泛型数组（数组项为带泛型的类）
/*
class Pairq<T> {

	private T first;
	private T last;

	public Pairq(T first, T last) {
		this.first = first;
		this.last = last;
	}

	public String toString() {
		return (first + " " + last);
	}
}

public class Test1 {
	public static void main(String[] args) throws Exception {
		String[] strings=new String[9];
		strings[0]="1";
		String[] stringss= {"1","1","2"};
		@SuppressWarnings("unchecked")
		Pairq<String>[] ps = (Pairq<String>[]) new Pairq[2];
		ps[0]=new Pairq("0", "0");
		ps[1]=new Pairq("1", "1");
		System.out.println(ps[0]);
		
		@SuppressWarnings("unchecked")
		Pairq<Integer>[] pi = (Pairq<Integer>[]) new Pairq[2];
		pi[0] = new Pairq(0, 0);
		pi[1] = new Pairq(1, 1);
		System.out.println(pi[1]);
	}
}

//在构造器中传入了 Class<T> 对象，通过 Array.newInstance(type, sz) 创建一个数组，这个方法会用参数中的 Class 对象作为数组元素的组件类型。这样创建出的数
//组的元素类型便不再是 Object，而是 T。这个方法返回 Object 对象，需要把它转型为数组。不过其他操作都不需要转型了，包括 rep() 方法，因为数组的实际类型
//与 T[] 是一致的。这是比较推荐的创建泛型数组的方法
/*
class Fruit {}
class Apple extends Fruit {}
class Jonathan extends Apple {
	String x;
	public Jonathan(String x) {
		super();
		this.x=x;
	}
}
class Orange extends Fruit {}
*/
/*
public class Test1 {
	public static void main(String[] args) {
		Fruit[] fruit = new Apple[10];
		fruit[0] = new Apple(); // OK
		fruit[1] = new Jonathan(); // OK
		// Runtime type is Apple[], not Fruit[] or Orange[]:运行时是Apple[]，不是Fruit[]或Orange[]
		try {
			// Compiler allows you to add Fruit:
			fruit[0] = new Fruit(); // 抛出java.lang.ArrayStoreException: 泛型.Fruit
		} catch (Exception e) {
			System.out.println(e);
		}
		try {
			// Compiler allows you to add Oranges:
			fruit[0] = new Orange(); // 抛出java.lang.ArrayStoreException: 泛型.Orange
		} catch (Exception e) {
			System.out.println(e);
		}
	}
}
*/
/*
public class Test1<T> {
   private T value;
   public Test1() {}
   public Test1(T val) { value = val; }
   public void set(T val) { value = val; }
   public T get() { return value; }
   public boolean equals(Object obj) {
   return value.equals(obj);
   }
   static void writeTo(List<? super Apple> apples) {
      apples.add(new Apple());
      apples.add(new Jonathan("f"));
      //apples.add(new Fruit()); // Error
  }
   public static void main(String[] args) {
       Test1<Apple> Apple = new Test1<Apple>(new Apple());
       Apple d = Apple.get();
       Apple.set(d);
       // Holder<Fruit> Fruit = Apple; // Cannot upcast
       Test1<? extends Fruit> fruit = Apple; // OK
       Fruit p = fruit.get();
       System.out.println(p.getClass().getSimpleName());//Apple
       d = (Apple)fruit.get(); // Returns ‘Object’
       try {
           Orange c = (Orange)fruit.get(); // No warning
       } catch(Exception e) { System.out.println(e); }
       // fruit.set(new Apple()); // Cannot call set()
       // fruit.set(new Fruit()); // Cannot call set()
       System.out.println(fruit.equals(d)); // OK
   }
}
*/
/*
//在方法内部，允许Apple及其子类add,外部调用，入参允许Apple及其父类。？？？？
class Fruit {}
class Apple extends Fruit {}
class Jonathan extends Apple {}
class Orange extends Jonathan {}
public class Test1 {
	public static void main(String[] args) {
		List<Apple> list1=new ArrayList<>();
		writeTo(list1);
		List<Fruit> list2=new ArrayList<>();
		writeTo(list2);
		List<Jonathan> list3=new ArrayList<>();
		//writeTo(list3);//Error
	}
   static void writeTo(List<? super Apple> apples) {//在方法内部，允许Apple及其子类add,外部调用，入参允许Apple及其父类
       apples.add(new Apple());
       apples.add(new Jonathan());
       apples.add(new Orange());
       //apples.add(new Fruit()); // Error
       System.out.println(apples.toString());
   }
}
*/
/*
public class Test1 {
	public static void main(String[] args) {
		List<Integer> list1=new ArrayList<>();
		writeTo(list1);
		List<Number> list2=new ArrayList<>();
		writeTo(list2);
		//writeTo(list3);//Error
	}
   static void writeTo(List<? super Integer> apples) {//在方法内部，允许Apple及其子类add,外部调用，入参允许Apple及其父类
       apples.add(Integer.valueOf(0));
       apples.add(1);
//       apples.add(1.0);
//       Number number=10;
//       apples.add(number);
       System.out.println(apples.toString());
   }
}
*/
/*
public class Test1 {
   // 把src的每个元素复制到dest中:
   public static <T> void copy1(List<? super T> dest, List<? extends T> src) {
   	System.out.print(src.size());
       T t = src.get(0); // compile error!
       dest.add(t); // compile error!
   }
   public static void main(String[] args) {
// copy List<Integer> to List<Number> ok:
   	List<Number> numList =new ArrayList<Number>();
   	numList.add(10.1);
   	List<Integer> intList =new ArrayList<>();
   	intList.add(101);
   	Test1.copy1(numList, intList);
   	System.out.print(numList);

// ERROR: cannot copy List<Number> to List<Integer>:
   	//Collections.copy(intList, numList)
   }
}
*/

class Studentq extends Personq{
	String name;
	String sex;
	Integer id;
	public Studentq(String name, String sex, Integer id) {
		super(name, sex);
		this.name = name;
		this.sex = sex;
		this.id = id;
	}

}
class Personq extends Creatureq{
	String name;
	String sex;
	public Personq(String name, String sex) {
		super(name);
		this.name = name;
		this.sex = sex;
	}

}
class Creatureq{
	String name;
	public Creatureq(String name) {
		this.name = name;
	}
}
class pa<T>{
	private T nameString;
	private T sex;
	public pa(Class<T> cls) throws InstantiationException, IllegalAccessException {
		nameString=cls.newInstance();
	}
}
public class Test1 {
	public static void main(String[] args) throws InstantiationException, IllegalAccessException {
		pa<String> p=new pa<>(String.class);
		List<? super Studentq> list;
		list = new ArrayList<Studentq>();
		list.add(new Studentq("a","b",12));
		//list.add( new Creatureq("creatureq"));
		list.add((Studentq) new Personq("a","b"));//出错
		
		List<? extends Creatureq> list1;
		list1=(List<? extends Creatureq>) list;
		list1.add(null);
		System.out.println(list1.get(0));//+" "+list1.get(1));
		//list1=(List<? extends Creatureq>) list.get(0);		
	}
}
